package dell.day01;

import dell.JDBCUtils.JDBCUtils;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

//将相应的查询语句封装起来，便于以后使用
public class BaseDAO {
    //通用的增删改操作代码
    public void update(Connection conn, String sql, Object...args) {
        PreparedStatement ps = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql语句
            ps = conn.prepareStatement(sql);
            //3.填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i + 1]);
            }
            //4.执行sql语句
            ps.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源
            JDBCUtils.closeResource(null, ps);
        }
    }
    //写一个通用的查询操作(返回表中单条记录的情况)
    public <T>T getInstance(Class<T> clazz,String sql,Object...args){
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            //定义为T类型，到用的时候传进来表的名字
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();
            //2.预编译sql语句，得到PreparedStatement对象
            ps = conn.prepareStatement(sql);
            //3.填充占位符
            for (int i=0;i<args.length;i++){
                ps.setObject(i+1,args[i]);
            }
            //4.执行executeQuery（），得到结果集：ResultSet
            rs = ps.executeQuery();
            //5.得到结果集的元数据：ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //6.(1)通过ResultSetMetaData得到columnCount(列的个数)，
            // columnLabel通过ResultSet得到列值
            int columnCount = rsmd.getColumnCount();
            if (rs.next()){
                T t = clazz.newInstance();
                for (int i=0;i<columnCount;i++){
                    //遍历每一个列
                    //获取列值
                    Object columnVal = rs.getObject(i + 1);
                    //获取列的列名：列的别名，使用类的属性名来写
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    //6.（2）使用反射，给对象的相应属性赋值
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    //允许访问私有的
                    field.set(t,columnVal);
                }
                return t;

            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //7.关闭资源
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;

    }
    // 写一个通用的查询操作(返回表中多条记录构成的集合的情况)
    public <T>List<T>getForList(Class<T> clazz,String sql,Object...args){
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            Connection conn = JDBCUtils.getConnection();
            ps = conn.prepareStatement(sql);
            for (int i=0;i<args.length;i++){
                ps.setObject(i+1,args[i]);
            }
            rs = ps.executeQuery();
            //获取结果集的元数据：ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //通过ResultSetMetaData获取结果集中的列数
            int columnCount = rsmd.getColumnCount();
            //创建集合对象
            ArrayList<T>list=new ArrayList<>();
            while (rs.next()){
                T t = clazz.newInstance();
                //处理结果集一行数据中的每一个列：给t对象指定的属性赋值
                for (int i=0;i<columnCount;i++){
                    //获取列值
                    Object columValue = rs.getObject(i + 1);
                    //获取每个列的列名
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    //给t对象指定的columnName属性，赋值为columnValue：通过反射·
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columValue);
                }
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.closeResource(null,ps,rs);
        }
       return null;
    }
}
